package bit.client.model;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jsoup.Connection.Response;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class ScoreGetter {
    private URL functionURL;
    private String viewstate;
    List<String> validYear;
    List<String> validSme;
    BitBasic basic;

    ScoreGetter(BitBasic basic) throws IOException {
        this.functionURL = basic.scoreURL;
        this.basic = basic;

        Response response = basic.get(functionURL);
        Document doc = response.parse();
        this.viewstate = doc.select("input[name=__VIEWSTATE]").first().attr("value");
        this.getYears(doc);
        this.getSemester(doc);

    }

    private void getYears(Document doc) {
        ArrayList<String> year = new ArrayList<String>();
        Elements optlist = doc.select("#ddlXN").first().select("option");
        for (Element opt : optlist) {
            if (opt.text().isEmpty()) continue;
            year.add(opt.text());
        }
        this.validYear = year;
    }

    private void getSemester(Document doc) {
        ArrayList<String> sem = new ArrayList<String>();
        Elements optlist = doc.select("#ddlXQ").first().select("option");
        for (Element opt : optlist) {
            if (opt.text().isEmpty()) continue;
            sem.add(opt.text());
        }
        this.validSme = sem;
    }

    public List<Score> queryAll() throws IOException {
        ArrayList<Score> scores = new ArrayList<Score>();
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("Button2", "%D4%DA%D0%A3%D1%A7%CF%B0%B3%C9%BC%A8%B2%E9%D1%AF");
        params.put("__VIEWSTATE", this.viewstate);
        params.put("ddlXN", "");
        params.put("ddlXQ", "");

        Response response = basic.post(functionURL, params);
        Document doc = response.parse();
        Elements trlist = doc.select("#DataGrid1 tbody").first().select("tr:not(.datagridhead)");
        for (Element tr : trlist) {
            Elements tdlist = tr.select("td");
            List<String> tdTextList = tdlist.eachText();
            Score score = new Score((String) tdTextList.get(0), (String) tdTextList.get(1), (String) tdTextList.get(2), Float.parseFloat((String) tdTextList.get(6)), Integer.parseInt((String) tdTextList.get(3)));
            scores.add(score);
        }

        return scores;
    }

    public List<Score> queryForAnnual(String year) throws OutOfValidYearOrSem, IOException {
        year = year.trim();
        if (!validYear.contains(year)) {
            throw new OutOfValidYearOrSem();
        }
        List<Score> scores = new ArrayList();
        Map<String, String> params = new HashMap();
        params.put("Button5", "%D4%DA%D0%A3%D1%A7%CF%B0%B3%C9%BC%A8%B2%E9%D1%AF");
        params.put("__VIEWSTATE", this.viewstate);
        params.put("ddlXN", year);
        params.put("ddlXQ", "");

        Response response = basic.post(functionURL, params);
        Document doc = response.parse();
        Elements trlist = doc.select("#DataGrid1 tbody").first().select("tr:not(.datagridhead)");
        for (Element tr : trlist) {
            Elements tdlist = tr.select("td");
            List<String> tdTextList = tdlist.eachText();
            Score score = new Score((String) tdTextList.get(0), (String) tdTextList.get(1), (String) tdTextList.get(2), Float.parseFloat((String) tdTextList.get(6)), Integer.parseInt((String) tdTextList.get(3)));
            scores.add(score);
        }

        return scores;
    }

    public List<Score> queryForSem(String year, String sem) throws OutOfValidYearOrSem, IOException {
        year = year.trim();
        sem = sem.trim();
        if (!validYear.contains(year) || !validSme.contains(sem)) {
            throw new OutOfValidYearOrSem();
        }
        List<Score> scores = new ArrayList();
        Map<String, String> params = new HashMap();
        params.put("Button1", "%D4%DA%D0%A3%D1%A7%CF%B0%B3%C9%BC%A8%B2%E9%D1%AF");
        params.put("__VIEWSTATE", this.viewstate);
        params.put("ddlXN", year);
        params.put("ddlXQ", sem);

        Response response = basic.post(functionURL, params);
        Document doc = response.parse();
        Elements trlist = doc.select("#DataGrid1 tbody").first().select("tr:not(.datagridhead)");
        for (Element tr : trlist) {
            Elements tdlist = tr.select("td");
            List<String> tdTextList = tdlist.eachText();
            Score score = new Score((String) tdTextList.get(0), (String) tdTextList.get(1), (String) tdTextList.get(2), Float.parseFloat((String) tdTextList.get(6)), Integer.parseInt((String) tdTextList.get(3)));
            scores.add(score);
        }

        return scores;
    }

    static class Score {
        public String code;
        public String name;
        public String type;
        public float credit;
        public int score;

        Score(String _code, String _name, String _type, float _credit, int _score) {
            this.code = _code;
            this.name = _name;
            this.type = _type;
            this.credit = _credit;
            this.score = _score;
        }


        @Override
        public String toString() {
            String str = "name: " + name + " score: " + score + " credit: " + credit;
            return str;
        }


        public static float ave(List<Score> list) {
            if (list.isEmpty()) return 0;
            float sum = 0;
            float creditSum = 0;
            for (Score score : list) {
                creditSum += score.credit;
                sum += score.credit * score.score;
            }
            return sum / creditSum;
        }
    }
}

